﻿using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

public class ZoneManager : MonoBehaviour
{
    public ZoneCamera _ZoneCamera;

    public ZoneFactory _ZoneFactory = null;
    public ZoneRender _ZoneRender = null;
    public ZoneFile _ZoneFile = null;
    public ZoneMediaManager _ZoneMediaManager = null;

    public ZoneUI _ZoneUI = null;

    #region Gizmos
    public static bool isDrawBorder = false;
    public static bool isDrawBlock = false;
    public static nLayerOrder LO = nLayerOrder.Null;

    public static void EnableGizmos(bool flag)
    {
        isDrawBorder = flag;

        for (int i = 0; i < _Groud.Count; ++i)
        {
            ObjectBase ob = (ObjectBase)_Groud[i];
            ob.Gizmos(flag);
        }
        _CurrentLayer.Gizmos(flag);

        //_DecoLayer.Gizmos(flag);
        //_BuildingLayer.Gizmos(flag);
        //_WallLayer.Gizmos(flag);
        //_FoundationLayer.Gizmos(flag);

    }

    public static void EnableBlock(bool flag)
    {
        isDrawBlock = flag;

        _CurrentLayer.Block(flag);
        for (int i = 0; i < _Groud.Count; ++i)
        {
            ObjectBase ob = (ObjectBase)_Groud[i];
            ob.Block(flag);
        }
        //_DecoLayer.Block(flag);
        //_WallLayer.Block(flag);
        //_BuildingLayer.Block(flag);
        //_FoundationLayer.Block(flag);

    }

    #endregion

    public static ZoneManager Instance;

    private void Awake()
    {
        Instance = this;
    }

    private void Start()
    {
        if (Application.platform == RuntimePlatform.Android)
            ZoneFileOnAndroid.UnZip();

        InitZoneManager();
    }

    #region 场景管理

    void InitZoneManager()
    {
        _ZoneMediaManager = new ZoneMediaManager();
        _ZoneFile = new ZoneFile();

        _ZoneRender = new ZoneRender();
        _ZoneFactory = new ZoneFactory(_ZoneRender);

        _ZoneUI.LoadDone();
        _ZoneUI.Go();
    }


    nZoneData datanZoneData;
    nZoneDataRelation datanZoneDataRelation;
    public static int CurIndex = -1;

    public void LoadZone(int index)
    {
        if (index == 0)
        {
            ClearZone();

            return;
        }

        ClearZone();

        CurIndex = index - 1;

        LoadZoneData(CurIndex);

    }

    void LoadZoneData(int index)
    {
        string content = _ZoneFile.GetZoneData(index);

        datanZoneData = JsonUtility.FromJson<nZoneData>(content);

        {
            nLayerData ud = (nLayerData)datanZoneData._groud;

            LayerObject co = new LayerObject(ud, ZoneCfg.CameraGroudLayer);
            co.Load();
            co._Object.tag = "Zone";
            co.SetVisible(false);

            _Groud = new List<ObjectBase>();
            _Groud.Add(co);

            _ZoneCamera.ResizeArea(ud._Width, ud._Height);
        }

        LoadZoneRelation(index);
    }

    void LoadZoneRelation(int index)
    {
        string content = _ZoneFile.GetZoneRelationData(index);

        if (string.IsNullOrEmpty(content))
            datanZoneDataRelation = new nZoneDataRelation();
        else
            datanZoneDataRelation = JsonUtility.FromJson<nZoneDataRelation>(content);

        VerticalCollate _VerticalCollate = new VerticalCollate();
        CellCenterCollate _CellCenterCollate = new CellCenterCollate();

        _DecoLayer = _ZoneFactory.AddLayer(nLayerOrder.Decos);
        _DecoLayer.Serialization(datanZoneDataRelation.deco_data);
        _DecoLayer.SetCollate(nLayerOrder.Decos, _CellCenterCollate);

        _WallLayer = _ZoneFactory.AddLayer(nLayerOrder.Wall);
        _WallLayer.Serialization(datanZoneDataRelation.wall_data);
        _WallLayer.SetCollate(nLayerOrder.Wall, _CellCenterCollate);

        _BuildingLayer = _ZoneFactory.AddLayer(nLayerOrder.Building);
        _BuildingLayer.Serialization(datanZoneDataRelation.building_data);
        _BuildingLayer.SetCollate(nLayerOrder.Building, _VerticalCollate);

        _FoundationLayer = _ZoneFactory.AddLayer(nLayerOrder.Foundation);
        _FoundationLayer.SetCollate(nLayerOrder.Foundation, _VerticalCollate);
        _FoundationLayer.Serialization(datanZoneDataRelation.foundation_data);

        _ZoneRender.Order();
    }

    public static UnitLayerObject _DecoLayer = null;
    public static UnitLayerObject _BuildingLayer = null;
    public static UnitLayerObject _WallLayer = null;
    public static UnitLayerObject _FoundationLayer = null;

    public static UnitLayerObject _CurrentLayer
    {
        get
        {
            return Instance._ZoneFactory.GetLayer(LO);
        }
    }
    public static List<ObjectBase> _Groud = new List<ObjectBase>();

    public void ClearZone()
    {
        if (CurIndex < 0)
            return;

        _BuildingLayer.Unload();
        _BuildingLayer = null;
        _WallLayer.Unload();
        _WallLayer = null;
        _FoundationLayer.Unload();
        _FoundationLayer = null;
        _DecoLayer.Unload();
        _DecoLayer = null;
        for (int i = 0; i < _Groud.Count; ++i)
        {
            ObjectBase ob = (ObjectBase)_Groud[i];
            ob.Unload();
            ob = null;
        }
        _Groud.Clear();

        CurIndex = -1;
    }

    public void SaveRelationZone()
    {
        nZoneDataRelation data = new nZoneDataRelation();
        data.zonename = "benzhen_template";

        LayerObject ob = (LayerObject)_Groud[0];

        {
            {
                _FoundationLayer.Save();

                data.foundation_data = _FoundationLayer.Deserialization();

            }

            {
                _WallLayer.Save();

                data.wall_data = _WallLayer.Deserialization();
            }

            {
                _BuildingLayer.Save();

                data.building_data = _BuildingLayer.Deserialization();
            }

            {
                _DecoLayer.Save();

                data.deco_data = _DecoLayer.Deserialization();
            }
        }


        string sdata = JsonUtility.ToJson(data);
        Instance._ZoneFile.SaveZoneRelationData(CurIndex, sdata);
    }

    public void SaveZone()
    {
        nZoneData data = new nZoneData();

        {
            LayerObject ob = (LayerObject)_Groud[0];
            ob.Save();
            data._groud = ob._layerData;
        }

        string sdata = JsonUtility.ToJson(data);
        Instance._ZoneFile.SaveZoneData(CurIndex, sdata);
    }
    #endregion

    #region 场景对象管理
    /// <summary>
    /// Zone的组织关系
    /// </summary>
    public static void PushZoneDeco(UnitObject uo)
    {
        _DecoLayer.Push(uo);
    }

    public static void PushZoneWall(UnitObject uo)
    {
        _WallLayer.Push(uo);
    }

    public static void PushZoneFoundation(UnitObject uo)
    {
        _FoundationLayer.Push(uo);
    }

    public static void PushZoneBuilding(UnitObject uo)
    {
        _BuildingLayer.Push(uo);
    }

    public static void PopZoneBuilding(int order)
    {
        _BuildingLayer.PopOrder(order);

    }
    #endregion

    #region 场景发生的事件
    public bool IsSelect(GameObject obj)
    {
        if (LO == nLayerOrder.Wall)
        {
            if (_WallLayer.IsSelect(obj))
                return true;
        }

        if (LO == nLayerOrder.Building)
        {
            if (_BuildingLayer.IsSelect(obj))
                return true;
        }

        if (LO == nLayerOrder.Foundation)
        {
            if (_FoundationLayer.IsSelect(obj))
                return true;
        }

        {
            if (_DecoLayer.IsSelect(obj))
                return true;
        }

        return false;
    }

    public void Seleted(GameObject obj)
    {
        if (obj == null)
            return;

        if (mSelectObject == null)
        {
            /// 上帝视角开启墙体和地面的控制
            if (LO == nLayerOrder.Wall)
                mSelectObject = _WallLayer.Selected(obj);

            if (LO == nLayerOrder.Building)
                mSelectObject = _BuildingLayer.Selected(obj);

            if (LO == nLayerOrder.Foundation)
                mSelectObject = _FoundationLayer.Selected(obj);

            if (LO == nLayerOrder.Decos)
                mSelectObject = _DecoLayer.Selected(obj);
        }

        if (mSelectObject != null)
        {
            delta_move_abs = Input.mousePosition;

            if (mSelectObject is UnitObject)
            {
                UnitObject uo = (UnitObject)mSelectObject;

                if (uo._GroudOrder != -1)
                    _CurrentLayer.CancelDone(uo);
            }

            mSelectObject.Gizmos(true);
            mSelectObject.Selected(true);
        }
    }

    public void Cancel(GameObject obj)
    {
        if (mSelectObject == null)
            return;

        {
            if (mSelectObject is UnitObject)
            {
                UnitObject uo = (UnitObject)mSelectObject;

                Vector3 pos = uo.GetUnitRhombusLeft4World();
                int order = ZoneManager._CurrentLayer.BlockFresh.GetClosePointOrder(pos, uo._VBOdata);

                if (!_ZoneFactory.GetCollider(uo._unitData._UnitType))
                {
                    StraightDropDown(uo, order);
                }
                else
                {
                    if (!TryPutDownWithCollider(uo, order))
                    {
                        Debug.LogError("Cancel");

                        ZoneUI.Instance.textHint.color = Color.red;

                        ResetPutDown(uo);
                    }
                }

                _CurrentLayer.Update(uo);
            }

            Clear();
        }

        for (int i = 0; i < _Groud.Count; ++i)
        {
            ObjectBase ob = (ObjectBase)_Groud[i];
            ob.SetColor(new Color(1, 1, 1, 1));
        }

        _BuildingLayer.SetColor(new Color(1, 1, 1, 1));
        _WallLayer.SetColor(new Color(1, 1, 1, 1));
        _FoundationLayer.SetColor(new Color(1, 1, 1, 1));
        _DecoLayer.SetColor(new Color(1, 1, 1, 1));

        _CurrentLayer.BlockFresh.SetEnable(false);
    }

    bool TryPutDownWithCollider(UnitObject uo, int order)
    {
        if (_CurrentLayer.BlockFresh.IsCanDone(order, uo._VBOdata))
        {
            StraightDropDown(uo, order);

            return true;
        }

        return false;
    }

    /// <summary>
    /// 直接放下
    /// </summary>
    void StraightDropDown(UnitObject uo, int order)
    {
        uo._GroudOrder = order;

        _CurrentLayer.Push(uo);

        uo.Gizmos(false);

    }

    /// <summary>
    /// 放回原来位置或者扔掉
    /// </summary>
    void ResetPutDown(UnitObject uo)
    {
        if (uo._GroudOrder == -1)
        {
            uo.Unload();

            _DecoLayer.Pop(uo._Object.GetInstanceID());
        }
        else
        {
            Vector3 donepos = _CurrentLayer.BlockFresh.GetClosePointRhombus(uo._GroudOrder, uo._VBOdata);

            uo.SetUnitRhombusLeft4World(donepos, uo._GroudOrder);

            List<int> grids_block = _CurrentLayer.BlockFresh.SetDone(uo._GroudOrder, uo._VBOdata);
            uo._unitData._order_block_4_groud = grids_block;
        }

        uo.Gizmos(false);
    }

    Vector3 delta_move_abs = Vector2.zero;

    public void Move(Vector2 delta)
    {
        if (mSelectObject == null)
        {
            _ZoneCamera.Move(delta);
            return;
        }

        if (!mSelectObject.isDrag)
            return;

        mSelectObject.Move(delta * 2);

        //  地面的碰撞盒可用
        _CurrentLayer.BlockFresh.SetEnable(true);

        _DecoLayer.SetColor(new Color(1, 1, 1, GetAlpha(nLayerOrder.Decos)));
        _BuildingLayer.SetColor(new Color(1, 1, 1, GetAlpha(nLayerOrder.Building)));
        _WallLayer.SetColor(new Color(1, 1, 1, GetAlpha(nLayerOrder.Wall)));
        _FoundationLayer.SetColor(new Color(1, 1, 1, GetAlpha(nLayerOrder.Foundation)));
        for (int i = 0; i < _Groud.Count; ++i)
        {
            ObjectBase ob = (ObjectBase)_Groud[i];
            ob.SetColor(new Color(1, 1, 1, GetAlpha(nLayerOrder.Groud)));
        }

        delta_move_abs = Input.mousePosition;

        if (mSelectObject is UnitObject)
        {
            UnitObject uo = (UnitObject)mSelectObject;

            if (_CurrentLayer.isLayerCollider)
            {
                Vector3 pos = uo.GetUnitRhombusLeft4World();
                int order = _CurrentLayer.BlockFresh.GetClosePointOrder(pos, uo._VBOdata);
                _CurrentLayer.BlockFresh.IsCanDone(order, uo._VBOdata);
            }
        }
    }

    float GetAlpha(nLayerOrder lt)
    {
        if (lt < LO)
            return 0.2f;

        return 1;
    }
    #endregion

    #region UI状态机
    public InputManager _InputManager;

    public EventSystem _EventSystem;

    ObjectBase _mSelectObject = null;

    ObjectBase mSelectObject
    {
        set
        {
            _mSelectObject = value;
        }

        get
        {
            return _mSelectObject;
        }
    }


    static UnitObject _mVirualObject = null;

    public static UnitObject mVirualObject
    {
        set
        {
            _mVirualObject = value;
        }
        get
        {
            return _mVirualObject;
        }
    }

    public void VirualObject(ObjectBase ob)
    {
        if (ob.isSelect)
        {
            mSelectObject = ob;

            Seleted(ob._Object);
        }
    }

    public string floor = string.Empty;

    public InputFloorComponent _InputFloorComponent = new InputFloorComponent();

    public void Clear()
    {
        mSelectObject = null;

        ZoneManager.Instance.floor = string.Empty;

        ZoneUI._clickOB = null;

    }
    #endregion

}
